package de.blitzcoder.collide.gui.textarea;

import java.lang.reflect.Field;
import org.gjt.sp.jedit.Mode;
import org.gjt.sp.jedit.Registers;
import org.gjt.sp.jedit.buffer.UndoManager;
import org.gjt.sp.jedit.syntax.ModeProvider;
import org.gjt.sp.jedit.textarea.Selection;
import org.gjt.sp.jedit.textarea.StandaloneTextArea;
import org.gjt.sp.util.StandardUtilities;

/**
 *
 * @author blitzcoder
 */
public class CollIDETextArea extends StandaloneTextArea {

    private static CollIDETextAreaPropertyManager propertyManager = new CollIDETextAreaPropertyManager();

    public CollIDETextArea() {
        super(propertyManager);
        setFileExtension("txt", "/modes/text.xml");
    }

    public static CollIDETextAreaPropertyManager getPropertyManager() {
        return propertyManager;
    }

    public void setFileExtension(String ext, String path) {
        Mode mode = new Mode(ext);
        mode.setProperty("file", path);
        ModeProvider.instance.addMode(mode);
        getBuffer().setMode(mode);

    }

    public void clearUndo() {
        try {
            Field f = getBuffer().getClass().getDeclaredField("undoMgr");
            f.setAccessible(true);
            ((UndoManager) f.get(getBuffer())).clear();
        } catch (Exception ex) {
            throw new Error(ex);
        }
    }

    /*
     * original method uses buffer.getContextSensitiveProperty,
     * this doesnt seem to work...
     */
    @Override
    public void lineComment() {
        if (!buffer.isEditable()) {
            getToolkit().beep();
            return;
        }

        String comment = "'";

        comment += ' ';

        buffer.beginCompoundEdit();

        int[] lines = getSelectedLines();

        try {
            for (int i = 0; i < lines.length; i++) {
                String text = getLineText(lines[i]);
                buffer.insert(getLineStartOffset(lines[i]) + StandardUtilities.getLeadingWhiteSpace(text),
                        comment);
            }
        } finally {
            buffer.endCompoundEdit();
        }

        selectNone();
    }

    public void insertTemplate(String template) {
        getBuffer().insert(getCaretPosition(), template.replace("\n", "\n" + getIndent(getCaretLine())));
    }

    public void surroundWith(String start, String end) {
        Selection[] sel = getSelection();
        if (sel.length > 0) {
            int endpos = sel[0].getEnd();
            int startpos = sel[0].getStart();
            getBuffer().insert(endpos, "\n" + end);
            getBuffer().insert(startpos, start + "\n");
        }
    }

    public void copy() {
        Registers.copy(this, '$');
    }

    public void cut() {
        Registers.cut(this, '$');
    }

    public void paste() {
        Registers.paste(this, '$');
    }

    public void blockComment() {
        if (isEditable()) {
            int[] selectedLines = getSelectedLines();
            Selection[] selection = getSelection();
            getBuffer().beginCompoundEdit();
            for (int i = 0; i < selectedLines.length; i++) {
                int line = selectedLines[i];
                String lineText = getLineText(line);
                if (lineText.trim().startsWith("'")) {
                    int pos = lineText.indexOf("'");
                    getBuffer().remove(getLineStartOffset(line) + pos, 1);
                } else {
                    getBuffer().insert(getLineStartOffset(line) + getIndentWidth(line), "'");
                }
            }
            getBuffer().endCompoundEdit();
            setSelection(selection);
        }
    }

    public int getIndentWidth(int line) {
        char[] c = getLineText(line).toCharArray();
        int width = 0;
        for (int i = 0; i < c.length; i++) {
            if (c[i] != 9 && c[i] != 32) // Space or Tab
                break;
            width++;
        }
        return width;
    }

    public String getIndent(int line) {
        return getLineText(line).substring(0, getIndentWidth(line));
    }

}
